﻿
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;

namespace test.kafka
{
    public static class EventBusExtension
    {
     

        public static void AddSubscrbe<TMssage>(this IBus bus, IServiceCollection services) where TMssage : IEventMessage
        {
            var provider =services.BuildServiceProvider();
            var handlerType = typeof(IEventHandler<TMssage>);            
            var handlers = provider.GetServices(handlerType).Cast<IEventHandler<TMssage>>();
            foreach (var handler in handlers) 
            {
                bus.Subscribe(handler);
            }
        }


        public static IServiceCollection AddEventBus( this IServiceCollection services)
        {
            services.AddSingleton(typeof(IBus), typeof(EventBus));
            return services;
        }

        public static IServiceCollection UseEventBus(this IServiceCollection services, Action<IBus> busAction)
        {
            var provider = services.BuildServiceProvider();
            if (provider == null) throw new ArgumentNullException(nameof(provider));
            if (busAction == null) throw new ArgumentNullException(nameof(busAction));


            var bus = provider.GetService<IBus>();

            busAction(bus);

            return services;
        }



        public static IServiceCollection AddRebusHandler<THandler>(this IServiceCollection services) where THandler : IEventHandler
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            RegisterType(services, typeof(THandler));
            return services;
        }

        static void RegisterType(IServiceCollection services, Type typeToRegister)
        {
            var implementedHandlerInterfaces = GetImplementedHandlerInterfaces(typeToRegister).ToArray();

            foreach (var handlerInterface in implementedHandlerInterfaces)
            {
                services.AddTransient(handlerInterface, typeToRegister);
            }
        }


        static IEnumerable<Type> GetImplementedHandlerInterfaces(Type type) =>
            type.GetInterfaces()
                .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEventHandler<>));

    }
}
